package net.aaa.hotel.util;

import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author: wangxiangnan
 * @time: 2020/8/10 15:47
 * @description:
 */
public class BaseDB {
    public static String driver = "com.mysql.cj.jdbc.Driver";//驱动  8.0+
    public static String url = "jdbc:mysql://172.16.22.155:3306/hotel?serverTimezone=Asia/Shanghai";//url
    public static String user = "root";//用户名
    public static String pass = "123456";//密码0

    static {  //静态代码块
        try {
            Class.forName(driver);//加载mysql驱动
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    /**
     * 根据数据建理连接
     *
     * @return
     * @throws SQLException
     */
    public static Connection getConn() throws SQLException {
        return DriverManager.getConnection(url, user, pass);
    }

    /**
     * [{id=123,name='张三'},{}]
     *
     * @param sql
     * @param params
     * @return
     * @throws SQLException
     */
    public static List<Map> queryMap(String sql, Object... params) {
        Connection con = null;
        List<Map> tabList = new ArrayList();
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            con = getConn();
            // tabList =
            ps = con.prepareStatement(sql);
            setParams(ps, params);
            rs = ps.executeQuery();
            //ResultSetMetaData  jdbc的元数据
            ResultSetMetaData rsmd = rs.getMetaData();
            //有多少列
            int count = rsmd.getColumnCount();
            while (rs.next()) {
                Map rowMap = new HashMap();
                for (int i = 1; i <= count; i++) {
                    //
                    rowMap.put(rsmd.getColumnLabel(i), rs.getObject(i));
                }
                tabList.add(rowMap);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            closeAll(rs, ps, con);
        }
        return tabList;

    }

    /**
     * 返回一个自动增长的主键
     *
     * @param sql
     * @param params
     * @return
     * @throws SQLException
     */
    public static int insertGetKey(String sql, Object... params) {
        Connection con = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            con = getConn();//与数据库建立连接

            ps = con.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
            setParams(ps, params);
            ps.executeUpdate();
            //获取结果集
            rs = ps.getGeneratedKeys();
            if (rs.next()) {
                //自动增长的主键
                return rs.getInt(1);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            closeAll(rs, ps, con);
        }
        return -1;
    }

    /**
     * List   <List>
     *
     * @param sql
     * @param params
     * @return
     * @throws SQLException
     */
    public static List<List> query(String sql, Object... params) throws SQLException {
        Connection con = null;
        List<List> tabList;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            con = getConn();
            tabList = new ArrayList();
            ps = con.prepareStatement(sql);
            setParams(ps, params);
            System.out.println(ps.toString());
            rs = ps.executeQuery();
            //获取jdbc的元数据
            ResultSetMetaData rsmd = rs.getMetaData();
            //获取列数
            int count = rsmd.getColumnCount();
            while (rs.next()) {
                //存放一行数据的一个集合
                List rowList = new ArrayList();
                for (int i = 1; i <= count; i++) {
                    rowList.add(rs.getObject(i));
                }
                tabList.add(rowList);//[[],[],[]]
            }
        } finally {
            closeAll(rs, ps, con);
        }
        return tabList;

    }

    /**
     * 增删改  通用的方法
     *
     * @param sql
     * @param params
     * @return
     * @throws SQLException
     */
    public static int update(String sql, Object... params) {
        Connection con = null;
        PreparedStatement ps = null;
        try {
            con = getConn();//数据库建立连接
            ps = con.prepareStatement(sql);//对sql进行预编译
            //对占位符进行赋值
            setParams(ps, params);
            //执行sql语句  返回的是受影响的行数
            return ps.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            closeAll(null, ps, con);
        }
        return -1;
    }

    /**
     * 对占位符进行赋值
     *
     * @param ps
     * @param params
     * @throws SQLException
     */

    public static void setParams(PreparedStatement ps, Object... params) throws SQLException {
        if (params.length > 0) {
            for (int i = 0; i < params.length; i++) {
                //第一个参数代表的是占位符是第几个   第二个参数 赋的值
                ps.setObject(i + 1, params[i]);
            }
        }
    }

    /**
     * 关闭数据
     *
     * @param rs
     * @param st
     * @param con
     */
    public static void closeAll(ResultSet rs, Statement st, Connection con) {
        if (rs != null) {
            try {
                rs.close();
                rs = null;
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (st != null) {
            try {
                st.close();
                st = null;
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (con != null) {
            try {
                con.close();
                con = null;
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 调用只含有in的存储过程
     */
    public static void getCall(String sql) {
        Connection con = null;
        CallableStatement callstatement = null;
        try {
            con = getConn();
            callstatement = con.prepareCall(sql);
//        if(obj.length>0){
//            for(int i=0;i<obj.length;i++){
//                //第一个参数代表的是占位符是第几个   第二个参数 赋的值
//                callstatement.setObject(i+1,obj[i]);
//            }
//        }
            //callstatement.registerOutParameter(1, java.sql.Types.INTEGER);//注册存储过程的out型参数类型；使用之前必须注册；
            callstatement.execute();//执行
            //System.out.println(callstatement.getInt(1));//获得存储过程的输出参数
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            closeAll(null, callstatement, con);
        }
        //return null;
    }

    /**
     * 函数有输出参数的存储过程
     */
    public static List<String> getCallOut(String sql, Object... obj) {
        List<String> list = new ArrayList<>();
        Connection con = null;
        CallableStatement callstatement = null;
        try {
            con = getConn();
            callstatement = con.prepareCall(sql);
            if (obj.length > 0) {
                for (int i = 0; i < obj.length; i++) {
                    //第一个参数代表的是占位符是第几个   第二个参数 赋的值
                    callstatement.registerOutParameter(i + 1, Types.VARCHAR);
                }
            }
            //callstatement.registerOutParameter(1, java.sql.Types.INTEGER);//注册存储过程的out型参数类型；使用之前必须注册；
            callstatement.execute();//执行
            for (int i = 0; i < obj.length; i++) {
                //第一个参数代表的是占位符是第几个   第二个参数 赋的值
                // callstatement.registerOutParameter(i+1, Types.VARCHAR);
                //System.out.println("剩余的房间数："+callstatement.getString(i+1));
                if (callstatement.getString(i + 1) != null) {
                    list.add(callstatement.getString(i + 1));
                }
            }
            //System.out.println(callstatement.getInt(1));//获得存储过程的输出参数
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            closeAll(null, callstatement, con);
        }
        return list;
    }
}